package xyz.csmcool.imroom.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.NotNull;
import xyz.csmcool.imroom.entity.Rooms;
import xyz.csmcool.imroom.entity.RoomsUser;
import xyz.csmcool.imroom.entity.UserFriend;
import xyz.csmcool.imroom.entity.vo.RoomUserVo;
import xyz.csmcool.imroom.feignclient.UserClient;
import xyz.csmcool.imroom.mapper.RoomsMapper;
import xyz.csmcool.imroom.mapper.RoomsUserMapper;
import xyz.csmcool.imroom.service.IRoomsUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import xyz.csmcool.imutil.ExceptionHandler.CommonException;
import xyz.csmcool.imutil.dto.RoomUserDto;
import xyz.csmcool.imutil.dto.RoomUsersDto;
import xyz.csmcool.imutil.dto.UserDto;
import xyz.csmcool.imutil.utils.SecretUtils;
import xyz.csmcool.imutil.webVo.MyPage;
import xyz.csmcool.imutil.webVo.ResultCode;
import xyz.csmcool.imutil.webVo.ResultVo;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author csmcool
 * @since 2022-08-08
 */
@Service
@RequiredArgsConstructor
public class RoomsUserServiceImpl extends ServiceImpl<RoomsUserMapper, RoomsUser> implements IRoomsUserService {

    final UserClient userClient;
    final RoomsUserMapper roomsUserMapper;
    final RoomsMapper roomsMapper;

    private static ExecutorService threadPool = new ThreadPoolExecutor
            (1, 30, 60L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(30), new ThreadFactory() {
                @Override
                public Thread newThread(@NotNull Runnable r) {
                    return new Thread(r, "ThreadPool thread: ");
                }
            });

    @Override
    public MyPage<UserDto> selectRoomUserInfo(Long page, Long limit, Integer roomId, Integer userId) {
        limit = limit < 1 ? 10 : limit;
        page = page < 1 ? 0 : (page - 1) * limit;
        List<Integer> integers;
        Long rid = 0L;
        if (roomId == 0) {
            integers = roomsUserMapper.selectRoomUsersByTime(page,limit,userId);
            rid = roomsUserMapper.selectRoomIdByTime(userId);
        } else {
            integers = roomsUserMapper.selectRoomUsers(page, limit, roomId, userId);
        }
        MyPage<UserDto> roomUserInfo = getRoomUserInfo(integers,roomId == 0 ?  Math.toIntExact(rid) : roomId);
        roomUserInfo.setPageNumber(rid);
        return roomUserInfo;
    }

    @Override
    public MyPage<UserDto> selectRoomUserInfoByName(Long page, Long limit, Integer roomId, Integer userId, String name) {
        limit = limit < 1 ? 10 : limit;
        page = page < 1 ? 0 : (page - 1) * limit;
        List<Integer> integers;
        if (roomId == 0) {
           integers = roomsUserMapper.selectAllUserIdByTime(userId);
        } else {
            integers  = roomsUserMapper.selectAllUserId(roomId, userId);
        }
        if(integers.size() == 0) {
            MyPage<UserDto> myPage = new MyPage<>();
            myPage.setContent(new LinkedList<UserDto>());
            myPage.setTotalElements(0);
            return myPage;
        }

        //封装请求数据
        RoomUserDto roomUserDto = new RoomUserDto();
        roomUserDto.setIds(integers);
        roomUserDto.setName(name);
        roomUserDto.setLimit(limit);
        roomUserDto.setPage(page);

        ResultVo<RoomUsersDto> roomUserInfoByName = userClient.getRoomUserInfoByName(roomUserDto);
        if (!roomUserInfoByName.getSucceed()) {
            throw new CommonException(ResultCode.CUSTOM_FAIL.setMessage("查询用户失败"));
        }
        RoomUsersDto data = roomUserInfoByName.getData();
        MyPage<UserDto> myPage = new MyPage<>();
        myPage.setTotalElements(data.getTotal());
        myPage.setContent(data.getDtos());
        return myPage;
    }

    /**
     * 得到当前聊天室的用户*
     *
     * @param page
     * @param limit
     * @param roomId
     * @param userId
     * @return
     */
    @Override
    public MyPage<UserDto> getCurrentRoomUsers(Long page, Long limit, Integer roomId, Integer userId) {
        limit = limit < 1 ? 10 : limit;
        page = page < 1 ? 0 : (page - 1) * limit;
        //查询用户
        List<Integer> list = roomsUserMapper.selectCurrentRoomUser(page, limit, roomId,userId);
        return getRoomUserInfo(list,roomId);
    }

    /**
     * 是否是聊天室用户*
     *
     * @param roomId
     * @param uid
     * @return
     */
    @Override
    public Integer isRoomUserAndMuted(Integer roomId, Integer uid) {
        Integer roomUser = roomsUserMapper.isRoomUser(roomId, uid);
        return roomUser;
    }

    /**
     * 删除聊天室所有用户
     *
     * @param roomId
     */
    @Override
    public void deleteRoomAllUser(Integer roomId) {
        QueryWrapper<RoomsUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("sjim_room",roomId);
        boolean remove = remove(queryWrapper);
        if(!remove) {
            remove(queryWrapper);
        }
    }

    /**
     * 禁言用户
     *
     * @param roomId
     * @param id
     * @param uid
     */
    @Override
    public void mutedUser(Integer roomId, Integer id, Integer uid) {
        roomsUserMapper.mutedUser(roomId, id, uid);
    }

    /**
     * 解封用户
     *
     * @param roomId
     * @param id
     * @param uid
     */
    @Override
    public void notMutedUser(Integer roomId, Integer id, Integer uid) {
        roomsUserMapper.notMutedUser(roomId, id, uid);
    }

    /**
     * 添加成员并且更新状态
     *
     * @param uid
     * @param roomId
     * @param isPass
     * @return
     */
    @Override
    public Boolean addOrUpdateRoomUser(Integer uid, Integer roomId, Integer isPass) {
        return roomsUserMapper.addNewRoomUser(uid, roomId, isPass);
    }

    /**
     * 退出聊天室
     *
     * @param uid
     * @param roomId
     */
    @Override
    public void exitCurrentRoom(Integer uid, Integer roomId) {
        Boolean room = roomsUserMapper.exitRoom(uid, roomId);
        if(!room) {
            throw new CommonException(ResultCode.CUSTOM_FAIL.setCode(90232).setMessage("你不能退出自己创建的聊天室"));
        }
    }

    /**
     * 加入我的聊天室的人查询
     *
     * @param page
     * @param limit
     * @param uid
     * @return
     * 这里采用JDK工具，也可以用async注解异步回调的方式完成。
     */
    @Override
    public MyPage<RoomUserVo> getAddMyRoom(Long page, Long limit, Integer uid) {
        MyPage<RoomUserVo> myPage = new MyPage<>();
        limit = limit < 1 ? 10 : limit;
        page = page < 1 ? 0 : (page - 1) * limit;
        Long finalLimit = limit;
        Long finalPage = page;
        CompletableFuture.allOf(
                CompletableFuture.runAsync(()->{
                    List<RoomUserVo> roomUserVos = roomsUserMapper.selectAddMyRoom(finalPage, finalLimit, uid);
                    if(roomUserVos.size() == 0) {
                        myPage.setContent(roomUserVos);
                        return;
                    }
                    List<Integer> uids = roomUserVos.stream().map(RoomUserVo::getUser).collect(Collectors.toList());
                    ResultVo<List<UserDto>> roomUserInfo = userClient.getRoomUserInfo(uids);
                    if (!roomUserInfo.getSucceed()) {
                        myPage.setContent(new LinkedList<>());
                        return;
                    }
                    List<UserDto> data = roomUserInfo.getData();
                    Map<Integer, String> userNames = data.stream().collect(
                            Collectors.toMap(UserDto::getId, UserDto::getUserName));
                    Map<Integer, String> avatars = data.stream().collect(
                            Collectors.toMap(UserDto::getId, UserDto::getAvatar));
                    for (RoomUserVo roomUserVo : roomUserVos) {
                        roomUserVo.setAvatar(avatars.get(roomUserVo.getUser()));
                        roomUserVo.setUserName(userNames.get(roomUserVo.getUser()));
                    }
                    myPage.setContent(roomUserVos);
                },threadPool),
                CompletableFuture.runAsync(()->{
                    Long result = 0L;
                    Long l = roomsUserMapper.selectAddMyRoomCount(uid);
                    if(l != null) {
                        result = l;
                    }
                    myPage.setTotalElements(result);
                },threadPool)
        ).join();
        return myPage;
    }

    /**
     * 审核朋友
     *
     * @param uid
     * @param roomId
     * @param isPass *
     */
    @Override
    public void examineRoomUser(Integer uid, Integer roomId, Integer isPass,Integer id) {
        if(isPass > 2 || isPass < 1) {
            throw new CommonException(ResultCode.CUSTOM_FAIL.setMessage("你已经加入该房间").setCode(90231));
        }

        Integer integer = roomsUserMapper.selectRoomUserStatus(roomId, uid,id);
        if(integer != 0) {
            throw new CommonException(ResultCode.CUSTOM_FAIL.setMessage("你已经加入该房间").setCode(90231));
        }

        Boolean aBoolean = roomsUserMapper.addNewRoomUser(uid, roomId, isPass);
        if(!aBoolean) {
            throw new CommonException(ResultCode.CUSTOM_FAIL.setMessage("你已经加入该房间").setCode(90231));
        }
    }

    /**
     * 通过密码加入房间
     *
     * @param uid
     * @param roomId
     * @param password
     */
    @Override
    public void joinRoomByPassword(Integer uid, Integer roomId, String password) {
        Rooms rooms = roomsMapper.selectRoomPasswd(roomId, uid);
        if(rooms == null) {
            throw new CommonException(ResultCode.CUSTOM_FAIL.setMessage("密码未输入"));
        }
        Integer integer = roomsUserMapper.selectJoinRoomUserStatus(roomId, uid);
        if(integer == null) {
            integer = 2;
        }
        if(integer == 1) {
            throw new CommonException(ResultCode.CUSTOM_FAIL.setMessage("你已经加入该房间").setCode(90232));
        }

        if(rooms.getIsProtected() && SecretUtils.encrypt(password).equals(rooms.getPassword())) {
            Boolean aBoolean = roomsUserMapper.addNewRoomUser(uid, roomId, 1);
            if(!aBoolean) {
                throw new CommonException(ResultCode.CUSTOM_FAIL.setMessage("你已经申请了，请勿重复申请").setCode(90231));
            }
        } else {
            throw new CommonException(ResultCode.CUSTOM_FAIL.setMessage("密码错误").setCode(90233));
        }
    }

    /**
     * 加入房间
     *
     * @param uid
     * @param roomId
     */
    @Override
    public void joinRoom(Integer uid, Integer roomId) {
        Rooms rooms = roomsMapper.selectRoomPasswd(roomId, uid);
        if(rooms == null || rooms.getIsProtected()) {
            throw new CommonException(ResultCode.CUSTOM_FAIL.setMessage("密码未输入"));
        }
        Integer integer = roomsUserMapper.selectJoinRoomUserStatus(roomId, uid);
        if(integer == null) {
            integer = 2;
        }
        if(integer == 1) {
            throw new CommonException(ResultCode.CUSTOM_FAIL.setMessage("你已经加入该房间").setCode(90232));
        }
        Boolean aBoolean = roomsUserMapper.addNewRoomUser(uid, roomId, 0);
        if(!aBoolean) {
            throw new CommonException(ResultCode.CUSTOM_FAIL.setMessage("你已经申请了，请勿重复申请").setCode(90231));
        }
    }

    MyPage<UserDto> getRoomUserInfo(List<Integer> list,Integer roomId) {
        MyPage<UserDto> myPage = new MyPage<>();
        if (list.size() == 0) {
            myPage.setContent(new LinkedList<UserDto>());
            myPage.setTotalElements(0);
            return myPage;
        }
        ResultVo<List<UserDto>> roomUserInfo = userClient.getRoomUserInfo(list);
        if (!roomUserInfo.getSucceed()) {
            throw new CommonException(ResultCode.CUSTOM_FAIL.setMessage("查询用户失败"));
        }
        List<UserDto> data = roomUserInfo.getData();
        myPage.setTotalElements(roomsUserMapper.selectCount(roomId));
        myPage.setContent(data);
        return myPage;
    }

}
